import Foundation

// MARK: - 用户中心信息响应
struct UserInfoResponse: Codable {
    let code: Int
    let message: String?
    let data: UserInfoData
}

// MARK: - 用户中心信息数据
struct UserInfoData: Codable {
    let id: Int
    let nickname: String
    let avatar: String
    let phone: String
    let integral: Int
    let experience: Int
    let level: Int
    let couponCount: Int
    let isVip: Bool
    let vipIcon: String
    let vipName: String
    let collectCount: Int
    let browseNum: Int
    let centerBanner: [CenterBanner]?
    let isPaidMember: Bool
    let paidMemberPaidEntrance: Int
}

// MARK: - 用户中心Banner
struct CenterBanner: Codable, Identifiable {
    let pic: String
    let id: Int
    let url: String
}

// MARK: - 用户信息
struct UserInfo: Codable {
    let id: Int?
    let nickname: String?
    let avatar: String?
    let phone: String?
    let nowMoney: Double?
    let integral: Int?
    let experience: Int?
    let level: Int?
    let levelName: String?
    let isPromoter: Bool?
    let payCount: Int?
    let spreadCount: Int?
    let isPaidMember: Bool?
    let collectCount: Int?
    let couponCount: Int?
    let browseNum: Int?
    let spreadTime: String?
    let userType: String?
    let status: Int?
    let isDel: Bool?
    let addTime: String?
    let lastTime: String?
    let cleanTime: String?
    let addres: String?
    let adminid: Int?
    let loginType: String?
    let paidMemberPaidEntrance: Int?
    
    // 计算属性：获取完整头像URL
    var fullAvatarUrl: String {
        return ImageHelper.shared.getImageUrl(avatar)
    }
}

// MARK: - 配置数据
struct ConfigData: Codable {
    let id: Int?
    let name: String
    let title: String?
    let formId: String?
    let value: String
    let status: Int?
    let createTime: String?
    let updateTime: String?
    let formName: String?
}

// MARK: - 商品分类
struct ProductCategory: Codable, Identifiable {
    let id: Int
    let pid: Int?
    let name: String
    let icon: String?
    let level: Int?
    let sort: Int?
    let isShow: Bool?
    let childList: [ProductCategory]?
    
    // 为了兼容性，保留原有的属性名
    var cateName: String {
        return name
    }
    
    var pic: String? {
        return icon
    }
    
    var children: [ProductCategory]? {
        return childList
    }
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(icon)
    }
}

// MARK: - 商品信息
struct Product: Codable, Identifiable {
    let id: Int
    let image: String?
    let sliderImage: [String]?
    let storeName: String?
    let storeInfo: String?
    let keyword: String?
    let barCode: String?
    let cateId: String?
    let price: Double
    let vipPrice: Double?
    let otPrice: Double?
    let postage: Double?
    let unitName: String?
    let sort: Int?
    let sales: Int?
    let stock: Int?
    let isShow: Bool?
    let isHot: Bool?
    let isBenefit: Bool?
    let isBest: Bool?
    let isNew: Bool?
    let description: String?
    let addTime: String?
    let isPostage: Bool?
    let merUse: Bool?
    let giveIntegral: Int?
    let cost: Double?
    let isSeckill: Bool?
    let isBargain: Bool?
    let isGood: Bool?
    let ficti: Int?
    let browse: Int?
    let codePath: String?
    let soureLink: String?
    let videoLink: String?
    let tempId: Int?
    let specType: Bool?
    let activity: ProductActivity?
    
    // CodingKeys for API mapping
    enum CodingKeys: String, CodingKey {
        case id, image, sliderImage, storeInfo, keyword, barCode, cateId
        case price, vipPrice, otPrice, postage, unitName, sort, sales, stock
        case isShow, isHot, isBenefit, isBest, isNew, description, addTime
        case isPostage, merUse, giveIntegral, cost, isSeckill, isBargain
        case isGood, ficti, browse, codePath, soureLink, videoLink
        case tempId, specType, activity
        case storeName = "name"  // API中的name字段映射到storeName
    }
    
    // 自定义解码器以处理字符串类型的价格
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 解码基本字段
        id = try container.decode(Int.self, forKey: .id)
        image = try container.decodeIfPresent(String.self, forKey: .image)
        sliderImage = try container.decodeIfPresent([String].self, forKey: .sliderImage)
        storeName = try container.decodeIfPresent(String.self, forKey: .storeName)
        storeInfo = try container.decodeIfPresent(String.self, forKey: .storeInfo)
        keyword = try container.decodeIfPresent(String.self, forKey: .keyword)
        barCode = try container.decodeIfPresent(String.self, forKey: .barCode)
        cateId = try container.decodeIfPresent(String.self, forKey: .cateId)
        unitName = try container.decodeIfPresent(String.self, forKey: .unitName)
        sort = try container.decodeIfPresent(Int.self, forKey: .sort)
        sales = try container.decodeIfPresent(Int.self, forKey: .sales)
        stock = try container.decodeIfPresent(Int.self, forKey: .stock)
        isShow = try container.decodeIfPresent(Bool.self, forKey: .isShow)
        isHot = try container.decodeIfPresent(Bool.self, forKey: .isHot)
        isBenefit = try container.decodeIfPresent(Bool.self, forKey: .isBenefit)
        isBest = try container.decodeIfPresent(Bool.self, forKey: .isBest)
        isNew = try container.decodeIfPresent(Bool.self, forKey: .isNew)
        description = try container.decodeIfPresent(String.self, forKey: .description)
        addTime = try container.decodeIfPresent(String.self, forKey: .addTime)
        isPostage = try container.decodeIfPresent(Bool.self, forKey: .isPostage)
        merUse = try container.decodeIfPresent(Bool.self, forKey: .merUse)
        giveIntegral = try container.decodeIfPresent(Int.self, forKey: .giveIntegral)
        isSeckill = try container.decodeIfPresent(Bool.self, forKey: .isSeckill)
        isBargain = try container.decodeIfPresent(Bool.self, forKey: .isBargain)
        isGood = try container.decodeIfPresent(Bool.self, forKey: .isGood)
        ficti = try container.decodeIfPresent(Int.self, forKey: .ficti)
        browse = try container.decodeIfPresent(Int.self, forKey: .browse)
        codePath = try container.decodeIfPresent(String.self, forKey: .codePath)
        soureLink = try container.decodeIfPresent(String.self, forKey: .soureLink)
        videoLink = try container.decodeIfPresent(String.self, forKey: .videoLink)
        tempId = try container.decodeIfPresent(Int.self, forKey: .tempId)
        specType = try container.decodeIfPresent(Bool.self, forKey: .specType)
        activity = try container.decodeIfPresent(ProductActivity.self, forKey: .activity)
        
        // 处理价格字段 - 支持字符串和数字类型
        if let priceDouble = try? container.decode(Double.self, forKey: .price) {
            price = priceDouble
        } else if let priceString = try? container.decode(String.self, forKey: .price),
                  let priceValue = Double(priceString) {
            price = priceValue
        } else {
            price = 0.0
        }
        
        // 处理vipPrice字段 - 支持字符串和数字类型
        if let vipPriceDouble = try? container.decode(Double.self, forKey: .vipPrice) {
            vipPrice = vipPriceDouble
        } else if let vipPriceString = try? container.decode(String.self, forKey: .vipPrice),
                  let vipPriceValue = Double(vipPriceString) {
            vipPrice = vipPriceValue
        } else {
            vipPrice = nil
        }
        
        // 处理otPrice字段 - 支持字符串和数字类型
        if let otPriceDouble = try? container.decode(Double.self, forKey: .otPrice) {
            otPrice = otPriceDouble
        } else if let otPriceString = try? container.decode(String.self, forKey: .otPrice),
                  let otPriceValue = Double(otPriceString) {
            otPrice = otPriceValue
        } else {
            otPrice = nil
        }
        
        // 处理postage字段 - 支持字符串和数字类型
        if let postageDouble = try? container.decode(Double.self, forKey: .postage) {
            postage = postageDouble
        } else if let postageString = try? container.decode(String.self, forKey: .postage),
                  let postageValue = Double(postageString) {
            postage = postageValue
        } else {
            postage = nil
        }
        
        // 处理cost字段 - 支持字符串和数字类型
        if let costDouble = try? container.decode(Double.self, forKey: .cost) {
            cost = costDouble
        } else if let costString = try? container.decode(String.self, forKey: .cost),
                  let costValue = Double(costString) {
            cost = costValue
        } else {
            cost = nil
        }
    }
    
    // 成员初始化器（用于从 GoodsListItem 等创建）
    init(
        id: Int,
        image: String?,
        sliderImage: [String]?,
        storeName: String?,
        storeInfo: String?,
        keyword: String?,
        barCode: String?,
        cateId: String?,
        price: Double,
        vipPrice: Double?,
        otPrice: Double?,
        postage: Double?,
        unitName: String?,
        sort: Int?,
        sales: Int?,
        stock: Int?,
        isShow: Bool?,
        isHot: Bool?,
        isBenefit: Bool?,
        isBest: Bool?,
        isNew: Bool?,
        description: String?,
        addTime: String?,
        isPostage: Bool?,
        merUse: Bool?,
        giveIntegral: Int?,
        cost: Double?,
        isSeckill: Bool?,
        isBargain: Bool?,
        isGood: Bool?,
        ficti: Int?,
        browse: Int?,
        codePath: String?,
        soureLink: String?,
        videoLink: String?,
        tempId: Int?,
        specType: Bool?,
        activity: ProductActivity?
    ) {
        self.id = id
        self.image = image
        self.sliderImage = sliderImage
        self.storeName = storeName
        self.storeInfo = storeInfo
        self.keyword = keyword
        self.barCode = barCode
        self.cateId = cateId
        self.price = price
        self.vipPrice = vipPrice
        self.otPrice = otPrice
        self.postage = postage
        self.unitName = unitName
        self.sort = sort
        self.sales = sales
        self.stock = stock
        self.isShow = isShow
        self.isHot = isHot
        self.isBenefit = isBenefit
        self.isBest = isBest
        self.isNew = isNew
        self.description = description
        self.addTime = addTime
        self.isPostage = isPostage
        self.merUse = merUse
        self.giveIntegral = giveIntegral
        self.cost = cost
        self.isSeckill = isSeckill
        self.isBargain = isBargain
        self.isGood = isGood
        self.ficti = ficti
        self.browse = browse
        self.codePath = codePath
        self.soureLink = soureLink
        self.videoLink = videoLink
        self.tempId = tempId
        self.specType = specType
        self.activity = activity
    }
    
    // 兼容性属性
    var name: String {
        return storeName ?? ""
    }
    
    var spec: String {
        return storeInfo ?? ""
    }
    
    // 计算属性：获取完整主图URL
    var fullImageUrl: String {
        return ImageHelper.shared.getImageUrl(image)
    }
    
    // 计算属性：获取完整轮播图URL数组
    var fullSliderImageUrls: [String] {
        return sliderImage?.map { ImageHelper.shared.getImageUrl($0) } ?? []
    }
}

// MARK: - 商品活动信息
struct ProductActivity: Codable {
    let type: String?
    let time: [String]?
    let title: String?
    let info: String?
    let price: Double?
}

// MARK: - 优惠券模型已移至 CouponResponse.swift

// MARK: - 轮播图
struct BannerItem: Codable {
    let id: Int?
    let title: String?
    let pic: String?
    let url: String?
    let status: Bool?
    let sort: Int?
    let createTime: String?
    let info: String?
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(pic)
    }
}

// MARK: - DIY页面数据
struct DIYPageData: Decodable {
    let title: String?
    let titleColor: String?
    let titleBgColor: String?
    let isBgColor: Int?
    let colorPicker: String?
    let isBgPic: Int?
    let bgPic: String?
    let bgTabVal: Int?
    let value: [String: DIYComponent]? // value 是一个对象，key 是组件名称
    
    // 将 value 对象转换为数组
    var components: [DIYComponent] {
        guard let value = value else { return [] }
        return value.map { key, component in
            var comp = component
            // 如果组件内部没有 name 字段，则使用外部的 key 作为名称
            if comp.name.isEmpty {
                comp.name = key
            }
            // 如果 timestamp 为 0 或 nil，使用 key 作为 timestamp（key 就是 timestamp 字符串）
            if comp.timestamp == nil || comp.timestamp == 0, let keyTimestamp = Int64(key) {
                comp.timestamp = keyTimestamp
            }
            return comp
        }.sorted { comp1, comp2 in
            // 先按 sort 排序，如果 sort 相同则按 timestamp 排序
            let sort1 = comp1.sort
            let sort2 = comp2.sort
            if sort1 != sort2 {
                return sort1 < sort2
            }
            // 如果 sort 相同，按 timestamp 排序
            let ts1 = comp1.timestamp ?? 0
            let ts2 = comp2.timestamp ?? 0
            return ts1 < ts2
        }
    }
}

// MARK: - DIY组件
struct DIYComponent: Decodable, Identifiable {
    var name: String // 组件名称，如 headerSerch, tabNav, news, titles, goodList
    let componentId: String? // 重命名避免与 Identifiable 的 id 冲突
    let title: String?
    let type: String?
    let sort: Int
    let isHide: Bool?
    var timestamp: Int64? // 时间戳（需要是 var 以便在 components 计算属性中修改）
    
    // 直接包含 DIYComponentValue 的所有字段（而不是嵌套）
    let valueData: DIYComponentValue
    
    // 计算属性：为了兼容性，提供 value 属性
    var value: DIYComponentValue? {
        return valueData
    }
    
    // Identifiable 协议
    var id: String {
        return name + (componentId ?? "") + String(sort)
    }
    
    enum CodingKeys: String, CodingKey {
        case componentId = "id", title, type, sort, isHide, name, timestamp
        // 不包含 value，因为所有字段都在顶层
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        componentId = try? container.decode(String.self, forKey: .componentId)
        title = try? container.decode(String.self, forKey: .title)
        type = try? container.decode(String.self, forKey: .type)
        sort = (try? container.decode(Int.self, forKey: .sort)) ?? 0
        isHide = try? container.decode(Bool.self, forKey: .isHide)
        // timestamp 可能是字符串或数字，需要特殊处理
        if let timestampString = try? container.decode(String.self, forKey: .timestamp),
           let timestampValue = Int64(timestampString) {
            timestamp = timestampValue
        } else {
            timestamp = try? container.decode(Int64.self, forKey: .timestamp)
        }
        // 从 JSON 中解码 name 字段，如果不存在则使用空字符串
        name = (try? container.decode(String.self, forKey: .name)) ?? ""
        
        // 直接从当前容器解码 DIYComponentValue 的所有字段
        // 因为 JSON 中这些字段就在组件对象的顶层
        valueData = try DIYComponentValue(from: decoder)
    }
}

struct DIYComponentValue: Decodable {
    // 通用字段
    let list: [DIYItem]?
    let tabConfig: TabConfig?
    let bgColor: ColorConfig?
    let bgStyle: StyleConfig?
    let mbConfig: StyleConfig?
    let lrConfig: StyleConfig?
    let upConfig: StyleConfig?
    let downConfig: StyleConfig?
    let contentStyle: StyleConfig?
    let contentConfig: StyleConfig?
    let isShow: Bool?
    let info: String?
    let pic: String?
    let url: String?
    
    // 头部搜索组件字段
    let logoConfig: ImageConfig?
    let logoFixConfig: ImageConfig?
    let searConfig: TabConfig?
    let hotWords: ListConfig?
    let placeWords: TextConfig?
    let searchConfig: TabConfig?
    let fromToType: String?
    let tabShowConfig: TabConfig? // 选项卡显示配置
    let swiperConfig: ListConfig? // 轮播图配置
    let docConfig: TabConfig? // 指示器配置
    let contentStyleBanner: StyleConfig? // 轮播图圆角配置
    let swiperStyleConfig: TabConfig? // 轮播图样式配置
    let docColor: ColorConfig? // 指示器颜色
    let txtStyle: TabConfig? // 指示器位置
    let borderColor: ColorConfig? // 搜索框边框颜色
    let textColor: ColorConfig? // 文字颜色（用于搜索框等）
    
    // 导航组件字段
    let listConfig: ListConfig?
    let menuConfig: ListConfig? // 导航菜单配置
    let number: TabConfig? // 显示个数配置
    let rowsNum: TabConfig? // 显示行数配置
    let navFontColor: ColorConfig? // 重命名避免冲突
    let navTitleColor: ColorConfig? // 导航组件的标题颜色
    let checkColor: ColorConfig?
    let themeStyleConfig: TabConfig?
    
    // 新闻播报组件字段
    let newsLogoConfig: ImageConfig? // 重命名避免冲突
    let directionConfig: TabConfig?
    let newsTextColor: ColorConfig? // 重命名避免冲突
    let textPosition: ListConfig?
    
    // 标题组件字段
    let titleConfig: TextConfig?
    let titleFuConfig: TextConfig?
    let titleRightConfig: TextConfig?
    let linkConfig: TextConfig?
    let bgImg: ImageConfig?
    let selectShow: TabConfig?
    let selectStyle: TabConfig?
    let bgTopStyle: StyleConfig?
    let bgDownStyle: StyleConfig?
    let textStyle: ListConfig?
    let fontSize: StyleConfig?
    let fontColor: ColorConfig?
    let fontFuSize: StyleConfig?
    let fontFuColor: ColorConfig?
    let fontRightSize: StyleConfig?
    let fontRightColor: ColorConfig?
    
    // 商品列表组件字段
    let numConfig: StyleConfig?
    let itemStyle: TabConfig?
    let goodsTabConfig: TabConfig? // 商品列表的 tabConfig，重命名避免与通用字段冲突
    let selectConfig: SelectConfig?
    let activeValueBrand: SelectConfig?
    let activeValueMer: SelectConfig?
    let goodsList: ListConfig?
    let goodsTitleColor: ColorConfig? // 重命名避免与标题组件的 titleColor 冲突
    let priceColor: ColorConfig?
    let soldColor: ColorConfig?
    let typeConfig: SelectConfig?
    let goodsSort: TabConfig?
    let sortCollation: TabConfig?
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(pic)
    }
    
    // 自定义解码，处理字段名称映射
    enum CodingKeys: String, CodingKey {
        case list
        case bgColor
        case bgStyle
        case mbConfig
        case lrConfig
        case upConfig
        case downConfig
        case contentStyle
        case contentConfig
        case isShow
        case info
        case pic
        case url
        case logoFixConfig
        case searConfig
        case hotWords
        case placeWords
        case searchConfig
        case fromToType
        case tabShowConfig
        case swiperConfig
        case docConfig
        case contentStyleBanner
        case swiperStyleConfig
        case docColor
        case txtStyle
        case borderColor
        case textColor
        case listConfig
        case menuConfig
        case number
        case rowsNum
        case checkColor
        case themeStyleConfig
        case directionConfig
        case textPosition
        case titleConfig
        case titleFuConfig
        case titleRightConfig
        case linkConfig
        case bgImg
        case selectShow
        case selectStyle
        case bgTopStyle
        case bgDownStyle
        case textStyle
        case fontSize
        case fontFuSize
        case fontFuColor
        case fontRightSize
        case fontRightColor
        case numConfig
        case itemStyle
        case selectConfig
        case activeValueBrand
        case activeValueMer
        case goodsList
        case priceColor
        case soldColor
        case typeConfig
        case goodsSort
        case sortCollation
        // 通用字段（可能被多个组件使用）
        case tabConfig
        case logoConfig
        case fontColor
        case titleColor
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 通用字段
        list = try? container.decode([DIYItem].self, forKey: .list)
        tabConfig = try? container.decode(TabConfig.self, forKey: .tabConfig)
        bgColor = try? container.decode(ColorConfig.self, forKey: .bgColor)
        bgStyle = try? container.decode(StyleConfig.self, forKey: .bgStyle)
        mbConfig = try? container.decode(StyleConfig.self, forKey: .mbConfig)
        lrConfig = try? container.decode(StyleConfig.self, forKey: .lrConfig)
        upConfig = try? container.decode(StyleConfig.self, forKey: .upConfig)
        downConfig = try? container.decode(StyleConfig.self, forKey: .downConfig)
        contentStyle = try? container.decode(StyleConfig.self, forKey: .contentStyle)
        contentConfig = try? container.decode(StyleConfig.self, forKey: .contentConfig)
        isShow = try? container.decode(Bool.self, forKey: .isShow)
        info = try? container.decode(String.self, forKey: .info)
        pic = try? container.decode(String.self, forKey: .pic)
        url = try? container.decode(String.self, forKey: .url)
        
        // 头部搜索组件字段
        let decodedLogoConfig = try? container.decode(ImageConfig.self, forKey: .logoConfig)
        logoConfig = decodedLogoConfig
        newsLogoConfig = decodedLogoConfig // 新闻组件也使用 logoConfig
        logoFixConfig = try? container.decode(ImageConfig.self, forKey: .logoFixConfig)
        searConfig = try? container.decode(TabConfig.self, forKey: .searConfig)
        hotWords = try? container.decode(ListConfig.self, forKey: .hotWords)
        placeWords = try? container.decode(TextConfig.self, forKey: .placeWords)
        searchConfig = try? container.decode(TabConfig.self, forKey: .searchConfig)
        fromToType = try? container.decode(String.self, forKey: .fromToType)
        tabShowConfig = try? container.decode(TabConfig.self, forKey: .tabShowConfig)
        swiperConfig = try? container.decode(ListConfig.self, forKey: .swiperConfig)
        docConfig = try? container.decode(TabConfig.self, forKey: .docConfig)
        contentStyleBanner = try? container.decode(StyleConfig.self, forKey: .contentStyleBanner)
        swiperStyleConfig = try? container.decode(TabConfig.self, forKey: .swiperStyleConfig)
        docColor = try? container.decode(ColorConfig.self, forKey: .docColor)
        txtStyle = try? container.decode(TabConfig.self, forKey: .txtStyle)
        borderColor = try? container.decode(ColorConfig.self, forKey: .borderColor)
        let decodedTextColor = try? container.decode(ColorConfig.self, forKey: .textColor)
        textColor = decodedTextColor
        
        // 导航组件字段
        listConfig = try? container.decode(ListConfig.self, forKey: .listConfig)
        menuConfig = try? container.decode(ListConfig.self, forKey: .menuConfig)
        number = try? container.decode(TabConfig.self, forKey: .number)
        rowsNum = try? container.decode(TabConfig.self, forKey: .rowsNum)
        let decodedFontColor = try? container.decode(ColorConfig.self, forKey: .fontColor)
        navFontColor = decodedFontColor // 导航组件使用 fontColor
        let decodedNavTitleColor = try? container.decode(ColorConfig.self, forKey: .titleColor)
        navTitleColor = decodedNavTitleColor // 导航组件使用 titleColor
        checkColor = try? container.decode(ColorConfig.self, forKey: .checkColor)
        themeStyleConfig = try? container.decode(TabConfig.self, forKey: .themeStyleConfig)
        
        // 新闻播报组件字段
        directionConfig = try? container.decode(TabConfig.self, forKey: .directionConfig)
        // 新闻组件使用 textColor（已在头部搜索组件字段中解码）
        newsTextColor = textColor
        textPosition = try? container.decode(ListConfig.self, forKey: .textPosition)
        
        // 标题组件字段
        titleConfig = try? container.decode(TextConfig.self, forKey: .titleConfig)
        titleFuConfig = try? container.decode(TextConfig.self, forKey: .titleFuConfig)
        titleRightConfig = try? container.decode(TextConfig.self, forKey: .titleRightConfig)
        linkConfig = try? container.decode(TextConfig.self, forKey: .linkConfig)
        bgImg = try? container.decode(ImageConfig.self, forKey: .bgImg)
        selectShow = try? container.decode(TabConfig.self, forKey: .selectShow)
        selectStyle = try? container.decode(TabConfig.self, forKey: .selectStyle)
        bgTopStyle = try? container.decode(StyleConfig.self, forKey: .bgTopStyle)
        bgDownStyle = try? container.decode(StyleConfig.self, forKey: .bgDownStyle)
        textStyle = try? container.decode(ListConfig.self, forKey: .textStyle)
        fontSize = try? container.decode(StyleConfig.self, forKey: .fontSize)
        fontColor = try? container.decode(ColorConfig.self, forKey: .fontColor)
        fontFuSize = try? container.decode(StyleConfig.self, forKey: .fontFuSize)
        fontFuColor = try? container.decode(ColorConfig.self, forKey: .fontFuColor)
        fontRightSize = try? container.decode(StyleConfig.self, forKey: .fontRightSize)
        fontRightColor = try? container.decode(ColorConfig.self, forKey: .fontRightColor)
        
        // 商品列表组件字段
        numConfig = try? container.decode(StyleConfig.self, forKey: .numConfig)
        itemStyle = try? container.decode(TabConfig.self, forKey: .itemStyle)
        let decodedTabConfig = try? container.decode(TabConfig.self, forKey: .tabConfig)
        goodsTabConfig = decodedTabConfig // 商品列表使用 tabConfig
        selectConfig = try? container.decode(SelectConfig.self, forKey: .selectConfig)
        activeValueBrand = try? container.decode(SelectConfig.self, forKey: .activeValueBrand)
        activeValueMer = try? container.decode(SelectConfig.self, forKey: .activeValueMer)
        goodsList = try? container.decode(ListConfig.self, forKey: .goodsList)
        let decodedTitleColor = try? container.decode(ColorConfig.self, forKey: .titleColor)
        goodsTitleColor = decodedTitleColor // 商品列表使用 titleColor
        priceColor = try? container.decode(ColorConfig.self, forKey: .priceColor)
        soldColor = try? container.decode(ColorConfig.self, forKey: .soldColor)
        typeConfig = try? container.decode(SelectConfig.self, forKey: .typeConfig)
        goodsSort = try? container.decode(TabConfig.self, forKey: .goodsSort)
        sortCollation = try? container.decode(TabConfig.self, forKey: .sortCollation)
    }
}

struct DIYItem: Codable {
    let id: String?
    let title: String?
    let pic: String?
    let url: String?
    let info: String?
    let sort: Int?
    let chiild: [DIYItem]? // 嵌套的子项（也用于存储 info 数组）
    let val: String? // 值字段
    let type: Int? // 类型字段（用于选项卡等）
    let img: String? // 图片字段（用于轮播图等）
    let style: String? // 样式字段（用于 textStyle 等）
    
    // 商品列表字段（goodsList.list中的item可能包含这些字段）
    let name: String? // 商品名称
    let image: String? // 商品图片
    let price: String? // 商品价格
    let unitName: String? // 单位名称
    let stock: Int? // 库存
    let sales: Int? // 销量
    let categoryName: String? // 分类名称
    let categoryId: Int? // 分类ID
    
    // 自定义解码：处理 info 字段（可能是 String 或数组）
    enum CodingKeys: String, CodingKey {
        case id, title, pic, url, info, sort, chiild, val, type, img, style
        case name, image, price, unitName, stock, sales, categoryName, categoryId
        case value // JSON 中的 value 字段映射到 val
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 处理 id 字段：可能是 String 或 Int
        if let idString = try? container.decode(String.self, forKey: .id) {
            id = idString
        } else if let idInt = try? container.decode(Int.self, forKey: .id) {
            id = String(idInt)
        } else {
            id = nil
        }
        
        title = try? container.decode(String.self, forKey: .title)
        pic = try? container.decode(String.self, forKey: .pic)
        url = try? container.decode(String.self, forKey: .url)
        sort = try? container.decode(Int.self, forKey: .sort)
        
        // 优先从 value 字段读取，如果没有则从 val 读取
        val = (try? container.decode(String.self, forKey: .value)) ?? (try? container.decode(String.self, forKey: .val))
        type = try? container.decode(Int.self, forKey: .type)
        img = try? container.decode(String.self, forKey: .img)
        style = try? container.decode(String.self, forKey: .style)
        
        // 商品列表字段
        name = try? container.decode(String.self, forKey: .name)
        image = try? container.decode(String.self, forKey: .image)
        price = try? container.decode(String.self, forKey: .price)
        unitName = try? container.decode(String.self, forKey: .unitName)
        stock = try? container.decode(Int.self, forKey: .stock)
        sales = try? container.decode(Int.self, forKey: .sales)
        categoryName = try? container.decode(String.self, forKey: .categoryName)
        categoryId = try? container.decode(Int.self, forKey: .categoryId)
        
        // 处理 chiild 和 info 字段
        // 首先尝试解码 chiild
        let decodedChiild = try? container.decode([DIYItem].self, forKey: .chiild)
        
        // 处理 info 字段：可能是 String 或数组
        if let infoArray = try? container.decode([DIYItem].self, forKey: .info) {
            // info 是数组，优先使用 chiild，如果 chiild 为空则使用 info 数组
            chiild = decodedChiild ?? infoArray
            info = nil
        } else if let infoString = try? container.decode(String.self, forKey: .info) {
            // info 是字符串
            chiild = decodedChiild
            info = infoString
        } else {
            // info 不存在
            chiild = decodedChiild
            info = nil
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try? container.encode(id, forKey: .id)
        try? container.encode(title, forKey: .title)
        try? container.encode(pic, forKey: .pic)
        try? container.encode(url, forKey: .url)
        try? container.encode(sort, forKey: .sort)
        try? container.encode(chiild, forKey: .chiild)
        try? container.encode(val, forKey: .val)
        try? container.encode(type, forKey: .type)
        try? container.encode(img, forKey: .img)
        
        // 商品列表字段
        try? container.encode(name, forKey: .name)
        try? container.encode(image, forKey: .image)
        try? container.encode(price, forKey: .price)
        try? container.encode(unitName, forKey: .unitName)
        try? container.encode(stock, forKey: .stock)
        try? container.encode(sales, forKey: .sales)
        try? container.encode(categoryName, forKey: .categoryName)
        try? container.encode(categoryId, forKey: .categoryId)
        
        // 编码 info 字段：如果是字符串则编码，如果是数组则编码为 info（从 chiild 恢复）
        if let infoString = info {
            try? container.encode(infoString, forKey: .info)
        } else if let chiildArray = chiild {
            // 如果 chiild 是从 info 数组解码来的，将其编码回 info
            try? container.encode(chiildArray, forKey: .info)
        }
    }
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(pic ?? img ?? image)
    }
}

struct TabConfig: Codable {
    let tabVal: Int?
}

struct StyleConfig: Codable {
    let val: Int
}

struct TextConfig: Codable {
    let val: String
}

struct ColorConfig: Codable {
    let color: [ColorItem]
}

struct ColorItem: Codable {
    let item: String
}

struct ImageConfig: Codable {
    let url: String?
}

struct ListConfig: Codable {
    let list: [DIYItem]?
    let tabVal: Int? // 用于 textStyle 等需要选择索引的配置
}

struct SelectConfig: Codable {
    let activeValue: [Int]?
}

// MARK: - 首页数据
struct IndexData: Codable {
    let banner: [BannerItem]?
    let menus: [MenuItem]?
    let info: IndexInfo?
    let lovely: [Product]?
    let likeInfo: LikeInfo?
    let bastList: [Product]?
    let firstList: [Product]?
    let benefit: [Product]?
    let hot: [Product]?
    let good: [Product]?
    let new: [Product]?
}

struct IndexInfo: Codable {
    let fastNumber: String?
    let servicePhone: String?
    let kfPhone: String?
    let openBargain: Bool?
    let openSeckill: Bool?
    let openStore: Bool?
    let storeName: String?
    let storeKeywords: String?
    let storeDesc: String?
    let wechatQrcode: String?
    let qqQrcode: String?
    let hotBanner: String?
    let bastBanner: String?
    let firstBanner: String?
    let benefitBanner: String?
    let likeInfoBanner: String?
    
    // 计算属性：获取完整二维码URL
    var fullWechatQrcodeUrl: String {
        return ImageHelper.shared.getImageUrl(wechatQrcode)
    }
    
    var fullQqQrcodeUrl: String {
        return ImageHelper.shared.getImageUrl(qqQrcode)
    }
}

struct LikeInfo: Codable {
    let title: String?
    let info: String?
    let banner: String?
    
    // 计算属性：获取完整横幅URL
    var fullBannerUrl: String {
        return ImageHelper.shared.getImageUrl(banner)
    }
}

// MARK: - 菜单项
struct MenuItem: Codable {
    let id: Int?
    let menuName: String
    let pic: String?
    let url: String?
    let sort: Int?
    let isShow: Bool?
    let info: String?
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(pic)
    }
}

// MARK: - 底部导航项
struct BottomNavItem: Codable {
    let name: String
    let pic: String?
    let picOn: String?
    let url: String?
    let info: String?
    
    // 计算属性：获取完整图片URL
    var fullPicUrl: String {
        return ImageHelper.shared.getImageUrl(pic)
    }
    
    var fullPicOnUrl: String {
        return ImageHelper.shared.getImageUrl(picOn)
    }
}

// MARK: - 购物车项
struct CartItem: Codable, Identifiable {
    let id: Int
    let uid: Int?
    let type: String?
    let productId: Int
    let productAttrUnique: String?
    var cartNum: Int  // 改为var，允许修改数量
    let addTime: String?
    let product: Product?
    let attrInfo: AttrInfo?
    let truePrice: Double?
    let vipTruePrice: Double?
    let costPrice: Double?
    let trueStock: Int?
    let productInfo: ProductInfo?
    var isSelected: Bool = false
    
    // 兼容性属性
    var quantity: Int {
        get { cartNum }
        set { cartNum = newValue }
    }
    
    // 计算总价
    var totalPrice: Double {
        return (truePrice ?? 0.0) * Double(cartNum)
    }
}

struct AttrInfo: Codable {
    let productId: Int?
    let sku: String?
    let stock: Int?
    let price: Double?
    let vipPrice: Double?
    let otPrice: Double?
    let weight: Double?
    let volume: Double?
    let barCode: String?
    let cost: Double?
    let image: String?
    
    // 计算属性：获取完整图片URL
    var fullImageUrl: String {
        return ImageHelper.shared.getImageUrl(image)
    }
}

struct ProductInfo: Codable {
    let image: String?
    let price: Double?
    let vipPrice: Double?
    let otPrice: Double?
    let storeName: String?
    let spec: String?  // 添加规格属性
    
    // 计算属性：获取完整图片URL
    var fullImageUrl: String {
        return ImageHelper.shared.getImageUrl(image)
    }
}

// MARK: - 文章
struct Article: Codable, Identifiable {
    let id: Int
    let cid: Int?
    let title: String
    let author: String?
    let imageInput: String?
    let synopsis: String?
    let content: String?
    let shareTitle: String?
    let shareContent: String?
    let visit: Int?
    let sort: Int?
    let url: String?
    let status: Bool?
    let addTime: String?
    let hide: Bool?
    let adminId: Int?
    let mer_id: Int?
    let isHot: Bool?
    let isBanner: Bool?
    
    // 计算属性：获取完整图片URL
    var fullImageUrl: String {
        return ImageHelper.shared.getImageUrl(imageInput)
    }
}

// MARK: - 商品列表响应模型
struct ProductListResponse: Codable {
    let page: Int
    let limit: Int
    let totalPage: Int
    let total: Int
    let list: [Product]
}

// MARK: - API响应包装
struct APIResponse<T: Codable>: Codable {
    let code: Int
    let message: String?
    let data: T?
    let status: Int?
    let time: String?
    
    // 计算属性：判断请求是否成功
    var isSuccess: Bool {
        return code == 200
    }
}

// MARK: - 只用于解码的 APIResponse（支持 Decodable 类型）
struct DecodableAPIResponse<T: Decodable>: Decodable {
    let code: Int
    let message: String?
    let data: T?
    let status: Int?
    let time: String?
    
    // 计算属性：判断请求是否成功
    var isSuccess: Bool {
        return code == 200
    }
}
